#include "GL/glut.h"

#include "draw.h"
#include "board.h"
#include "timedCallback.h"

// members of v must have isDead() member function
template <typename T>
static
void removeDead(vector<T> &v) {
	typename std::vector<T>::iterator i = v.begin();

	while (i != v.end()) {
		if ((*i).isDead()) {
			i = v.erase(i);
		} else {
			i++;
		}
	}
}

// callbacks are run, dead callbacks are removed
void runCallbackPhase() {
	Board *b = getCurrentBoard();

	// run callbacks AND remove dead ones

	// illusionist
	b->getIll().invokeCallback();

	// enemies
	vector<Guard> &guards = b->getGuards();
	for (size_t i = 0; i < guards.size(); i++) {
		guards[i].invokeCallback();
	}

	vector<Dog> &dogs = b->getDogs();
	for (size_t i = 0; i < dogs.size(); i++) {
		dogs[i].invokeCallback();
	}

	vector<SG> &sgs = b->getSgs();
	for (size_t i = 0; i < sgs.size(); i++) {
		sgs[i].invokeCallback();
	}

	// illusions
	vector<Food> &foods = b->getFoods();
	for (size_t i = 0; i < foods.size(); i++) {
		foods[i].invokeCallback();
	}

	vector<DeadBody> &deadBodies = b->getDeadBodies();
	for (size_t i = 0; i < deadBodies.size(); i++) {
		deadBodies[i].invokeCallback();
	}	
}

// enemies look for things that interest them
void runEnemyPhase() {
	Board *b = getCurrentBoard();

	// enemies looking
	vector<Guard> &guards = b->getGuards();
	for (size_t i = 0; i < guards.size(); i++) {
		guards[i].look();
	}

	vector<Dog> &dogs = b->getDogs();
	for (size_t i = 0; i < dogs.size(); i++) {
		dogs[i].look();
	}

	vector<SG> &sgs = b->getSgs();
	for (size_t i = 0; i < sgs.size(); i++) {
		sgs[i].look();
	}

}

// dead enemies and powers are removed
void runRemoveDeadPhase() {
	Board *b = getCurrentBoard();

	// remove all dead enemies
	removeDead<Guard>(b->getGuards());
	removeDead<Dog>(b->getDogs());
	removeDead<SG>(b->getSgs());

	// remove all dead powers
	removeDead<Food>(b->getFoods());
	removeDead<DeadBody>(b->getDeadBodies());
}

void idle ()
{
	if (atTitle() || atCutScene() || atPause() || atEnding()) {
		glutPostRedisplay();
		return;
	}

	if (getCurrentBoard() == NULL) {
		return;
	}

	// poll all of the callbacks
	runCallbackPhase();

	// enemies look
	runEnemyPhase();

	// remove all dead objects, enemies and powers
	runRemoveDeadPhase();

	glutPostRedisplay();
}
